package cn.tannn.tregistry.client;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 线程
 *
 * @author <a href="https://tannn.cn/">tan</a>
 * @date 2024/4/28 9:09
 */

public class TnExecutors {
    private static final Logger logger = LoggerFactory.getLogger(TnExecutors.class);


    /**
     * 健康状况
     */
    ScheduledExecutorService providerExecutor;
    /**
     * uri 检查
     */
    ScheduledExecutorService urlExecutor;

    public void start() {
        logger.info(" ====>>>> [tregistry] : start with health checker.");
        providerExecutor = Executors.newScheduledThreadPool(1);
        urlExecutor = Executors.newScheduledThreadPool(1);
    }

    public void stop() {
        logger.info(" ====>>>> [tregistry] : stop with health checker.");
        gracefulShutdown(providerExecutor);
        gracefulShutdown(urlExecutor);
    }

    /**
     * 健康上报
     * @param callback Callback
     */
    public void providerCheck(Callback callback) {
        providerExecutor.scheduleAtFixedRate(() -> {
            try {
                callback.call();
            } catch (Exception e) {
                logger.error(e.getMessage());
            }
        }, 5, 5, TimeUnit.SECONDS);
    }

    /**
     * 注册中心集群列表探活
     * @param callback Callback
     */
    public void servicesUrlCheck(Callback callback) {
        urlExecutor.scheduleWithFixedDelay(() -> {
            try {
                callback.call();
            } catch (Exception e) {
                logger.error(e.getMessage());
            }
        }, 1, 5, TimeUnit.SECONDS);
    }

    /**
     * 下线线程
     *
     * @param executorService 线程
     */
    private void gracefulShutdown(ScheduledExecutorService executorService) {
        executorService.shutdown();
        try {
            executorService.awaitTermination(1000, TimeUnit.MILLISECONDS);
            if (!executorService.isTerminated()) {
                executorService.shutdownNow();
            }
        } catch (InterruptedException e) {
            // ignore
        }
    }

    /**
     * 钩子
     */
    public interface Callback {
        void call() throws Exception;
    }
}
